#include <stdio.h>
//#include <string.h>

#include "hal.h"
#include "cc_radio.h"
#include "myglobals.h"

/*
Inhalt:

Interruptroutine zum SFD merken und SFD Flag setzen
Initialisierungsroutine
prepareReceive Routine
Daten Einleseroutine

swnotes:
newRXData wird gesetzt wenn SFD aktiv.
danach muss Paket geholt werden
myRadioGetRXData(rx_data)
myRadioInit(freq)
myRadioReceive()
gebraucht wird auch ersatz für
SPP_RX_STRUCT
myRadioIdle();
myRadioOff();
*/

//UINT8 rx_len = 0;



UINT8 rx_len;
BITVAR rx_crcerr;
volatile BITVAR rx_newSFD;
volatile mytime32 rx_sfdtime;

UINT16 theSioInPos;
UINT8 theSioInpLine[SIO_INBUFLEN];
UINT8 sio_rx_has_line; 
UINT8 sio_bytemode;
UINT16 sio_rx_len;

volatile UINT8 timer3Interrupt;

static UINT8 (*rxCallBackFunction)(void);

UINT8 myRadioGetRXData(UINT8* rx_ptr)
{
// liefert 1 wenn gute Daten, sonst 0
UINT8 tio = 200;
UINT8 i;
while(tio && !(RFIF & IRQ_FIFOP)) {mydelayus(50) ; tio--;};
rx_len = RFD;
rx_crcerr = (rx_len & 0x80 ? 1 :0);
rx_len &= 0x7F;
for(i=0; i<(rx_len); i++){
   while(tio && !(RFIF & IRQ_FIFOP)) {mydelayus(50) ; tio--;};
   *rx_ptr++ = RFD;
   };
// die letzten beiden Werte sind RSSI und LQI
rx_len -= 2;
if (tio > 0)
 if (!rx_crcerr)
  if (rxCallBackFunction() == TRUE) {
   
   return(1);
   }
return 0;
}

void myRadioSetRxCallBackFunction(UINT8 (*callBackFunction)(void))
{
   rxCallBackFunction = callBackFunction;
} // Ends sppSetRxCallBackFunction()

void myRadioInit(UINT8 chan)
{

     INT16 myfreq = 5*(chan-11) + 357;
	 TXCTRLL = 0x5f; //nach d´Datasheet, ca. -0.5 dBM Output
     FSCTRLL = (BYTE) myfreq;
     FSCTRLH = ((FSCTRLH & ~0x03) | (BYTE)((myfreq >> 8) & 0x03));
     // turning on power to analog part of radio and waiting for voltage regulator.
     RFPWR = 0x04;
     while((RFPWR & 0x10)) { ; };
      // Turning off Address Decoding
     MDMCTRL0H &= ~ADR_DECODE;
      // Setting for AUTO CRC
     MDMCTRL0L |= AUTO_CRC;
      // Turning on AUTO_TX2RX
     FSMTC1 = ((FSMTC1 & (~AUTO_TX2RX_OFF & ~RX2RX_TIME_OFF))  | ACCEPT_ACKPKT);
      // Turning off abortRxOnSrxon.
     FSMTC1 &= ~0x20;
   // Flushing both Tx and Rx FiFo. The flush-Rx is issued twice to reset the SFD.
   // Calibrating the radio and turning on Rx to evaluate the CCA.
   //  SRXON;
  //     SFLUSHTX;
  //   SFLUSHRX;
  //   SFLUSHRX;
  //   STXCALN;
  //   ISSTART;
}

// Empfang vorbereiten
/*
void myRadioIdle(void)
{
INT_GLOBAL_ENABLE(INT_OFF);
RFIM &= ~IRQ_SFD; //sfd IRQ aktivieren
newSFD = 0;
ISRFOFF;
RFIF = 0;
INT_SETFLAG(INUM_RF,INT_CLR);
INT_ENABLE(INUM_RF,INT_ON);
INT_GLOBAL_ENABLE(INT_ON);
}
*/

void myRadioOff(void)
{
INT_GLOBAL_ENABLE(INT_OFF);
RFIM &= ~IRQ_SFD; //sfd IRQ deaktivieren
rx_newSFD = 0;
ISRFOFF;
RFPWR = 0x0C;
RFIF = 0;
INT_SETFLAG(INUM_RF,INT_CLR);
INT_ENABLE(INUM_RF,INT_ON);
INT_GLOBAL_ENABLE(INT_ON);
}



void myRadioReceive(void)
{
// Setting the number of bytes to assert the FIFOP flag
//   IOCFG0 = 7;
  rx_newSFD = 0;
  RFIF &= ~IRQ_SFD; //sfd IRQ aktivieren
  ISFLUSHRX;
  ISFLUSHRX;
  RFIF &= ~IRQ_FIFOP;
  ISRXON;
//  ISSTART;
     // Clearing the RF interrupt flags and enable mask and enabling RF interrupts
  RFIF = 0;
  RFIM |= IRQ_SFD; //sfd IRQ aktivieren
  INT_SETFLAG(INUM_RF,INT_CLR);
  INT_ENABLE(INUM_RF,INT_ON);
  INT_GLOBAL_ENABLE(INT_ON);
}

//-----------------------------------------------------------------------------
// See cul.h for a description of this function.
//-----------------------------------------------------------------------------
#ifdef __SDCC__
void spp_rf_IRQ(void)  __interrupt (RF_VECTOR)
#else
#pragma vector=RF_VECTOR
__interrupt void spp_rf_IRQ(void)
#endif
{
   INT_GLOBAL_ENABLE(INT_OFF);
//   printf("INT\n");
// SK added next lines for SFD memory
   T3CTL |= 0x04;     // reset counter timer 3
   TIMER3_RUN(TRUE);  // start timer3
   timer3Interrupt=0;
    if(RFIF & IRQ_SFD)
     {
	rx_sfdtime.b.t0 = ST0;
	rx_sfdtime.b.t1 = ST1;
	rx_sfdtime.b.t2 = ST2;
	rx_sfdtime.b.t3 = 0;
	RFIM &= ~IRQ_SFD; //sfd IRQ abschalten. Muss explizit wieder aktiviert werden
	rx_newSFD = 1;
     }	
   RFIF = 0x00;                      // Clear all interrupt flags
   INT_SETFLAG(INUM_RF, INT_CLR);    // Clear MCU interrupt flag
   INT_GLOBAL_ENABLE(INT_ON);
//   if (USESIO) printf("\n###\n");
   if (USESIO) putchar('#');
}

void prepareUserPacket(BYTE* buf, BYTE len)
{
BYTE i;

  ISFLUSHTX; // Making sure that the TX FIFO is empty.
  RFIF &= ~IRQ_TXDONE;
  RFD = len+2; // 2 für CRC
  // Inserting data
    for(i=0;i<len;i++){
        RFD = buf[i];
    }
}

void firePacketAndWait(UINT8 rfoff)
{
  INT16 tmpctr = 0;
  RFIM &= ~IRQ_SFD; // Disable SFD IRQ, wird auch beim Senden erzeugt
  ISTXON; // Sending
  // Waiting for transmission to finish
  while(!(RFIF & IRQ_TXDONE) ) tmpctr++;
  {;}
  RFIF &= ~IRQ_TXDONE;
  if (rfoff) ISRFOFF;
}



//-----------------------------------------------------------------------------
// See cul.h for a description of this function.
//-----------------------------------------------------------------------------
//#pragma vector=RFERR_VECTOR
#ifdef __SDCC__
void rf_error_IRQ(void) __interrupt (RFERR_VECTOR)
#else
#pragma vector=RFERR_VECTOR
__interrupt void rf_error_IRQ(void)
#endif
{
   INT_GLOBAL_ENABLE(INT_OFF);

   // If Rx overflow occurs, the Rx FiFo is reset.
   // The Rx DMA is reset and reception is started over.
   if(FSMSTATE == 17)
   {
      STOP_RADIO();
      ISFLUSHRX;
      ISFLUSHRX;
      ISRXON;
   }
   else if(FSMSTATE == 56)
   {
      ISFLUSHTX;
   }
   if (USESIO) printf("\nRF ERR !!\n ");
   INT_SETFLAG(INUM_RFERR,INT_CLR);

   INT_GLOBAL_ENABLE(INT_ON);
}

void mydelayms(volatile BYTE mdl)
{
UINT8 i;
while(mdl--)
  for(i=5;i>0;i--) mydelayus(200);
}

// --------------------------------------------------------------

#ifdef __SDCC__
void uart0_rx_IRQ(void) __interrupt (URX0_VECTOR)
#else
#pragma vector=URX0_VECTOR
__interrupt void uart0_rx_IRQ(void)
#endif
{
static UINT8 c;
c = U0DBUF;
//putchar(c);
if ((sio_bytemode < 0x80) && (c >= 0x80)) sio_bytemode = c;
else
if (sio_bytemode >= 0x80)
  {
   if ((theSioInPos < SIO_INBUFLEN) && (!sio_rx_has_line)) theSioInpLine[theSioInPos++] = c;
   sio_bytemode--;
  }
else
  if (!sio_rx_has_line)
 {
      if (((c==0x0d) || (c==0x0a)) && theSioInPos)
            { // cr 
              theSioInpLine[theSioInPos] = 0;
	      sio_rx_has_line = 1; // Zeile eingelesen
	      sio_rx_len = theSioInPos;
	      theSioInPos = 0;
	      if (sio_rx_len==2) 
		if (theSioInpLine[0]=='x')
		   if (theSioInpLine[1]=='b')
		   {
		  //reset durch Hund
        WDT_SET_TIMEOUT_PERIOD(SEC_1);
        WDT_RESET();
        WDT_ENABLE();
//	printf("\n@HUND ist raus!\n");
		   }
	    }
      else if ((c >= 0x20) && (theSioInPos < SIO_INBUFLEN) ) 
      	theSioInpLine[theSioInPos++] = c;
 } // (!rx_has_line)
URX0IF = FALSE;
INT_SETFLAG(INUM_URX0,INT_CLR);
}



#ifdef __SDCC__
void mydelayus(volatile BYTE mdl)
{
// ertser Operand in register R1
// R1 sollte aber erhalten bleiben
  _asm
  push 1
  push 2
  mov R1, DPL
outer:
#ifndef CC1110
  mov R2, #6
  nop
  nop
  nop
#else
  mov R2, #3
  nop
#endif
// Inner:
inner:
  nop
  djnz R2,inner
  djnz R1,outer
  pop 2
  pop 1
  _endasm;
// inner loop braucht 4 * L2 = I
// Outer braucht 8 + I ( I = 2
}
#else
void mydelayus(volatile BYTE mdl)
{
// ertser Operand in register R1
// R1 sollte aber erhalten bleiben
  asm (" push 1");
  asm (" push 2");
// Outer
  asm ("mov R2, #6");
  asm (" nop");
  asm (" nop");
  asm (" nop");
  // Inner:
  asm (" nop");
  asm (" djnz R2,0x09");
  asm (" djnz R1,0x04");
  asm ("        pop 2");
  asm ("        pop 1");
// inner loop braucht 4 * L2 = I
// Outer braucht 8 + I ( I = 2
}
#endif

volatile INT32 currtime32(void)
{
mytime32 x;
BITVAR eaflag = EA;
  EA = 0;
#ifndef CC1110
  x.b.t0 = ST0;
  x.b.t1 = ST1;
  x.b.t2 = ST2;
#else
  x.b.t0 = WORTIME0;
  x.b.t1 = WORTIME1;
  x.b.t2 = 0;
#endif
x.b.t3 = 0;
  EA = eaflag;
return x.t32;
}

void rf_Timer3Init(UINT16 usec)
{
    usec=usec >> 2;
    T3CTL   = 0xEE; //Interrupt enabled and modulo counter Tick freq/128
    T3CCTL0 = 0x00; 
    T3CC0   = usec; //set overflow to usec
    T3CCTL1 = 0x00; 
    T3CC1   = 0x00; 
}
